﻿using MQTT.Server.DataBase;
using MQTT.Server.ExtensionServer.MQTTClient;
using MQTT.Server.GlobalConfig;
using MQTT.Server.Helper;
using MQTTnet;
using MQTTnet.Internal;
using MQTTnet.Packets;
using MQTTnet.Protocol;
using MQTTnet.Server;
using SqlSugar;
using System;
using System.Diagnostics.Tracing;

namespace MQTT.Server.Controllers
{

    public class MqttServerController
    {
        private readonly ISqlSugarClient _sqlSugar;

        private readonly AppConfig _appConfig;

        private readonly IWebHostEnvironment _environment;

        private readonly ILogger<MqttServerController> _logger;

        private readonly MqttServer _mqttServer;


        public MqttServerController(ISqlSugarClient sqlSugar,
                              AppConfig appConfig,
                              IWebHostEnvironment environment,
                              ILogger<MqttServerController> logger,
                              MqttServer mqttServer)
        {
            _sqlSugar = sqlSugar;
            _appConfig = appConfig;
            _environment = environment;
            _logger = logger;
            _mqttServer = mqttServer;
            // Inject other services via constructor.
        }

        #region Server

        /// <summary>
        /// 客户端请求建立连接   可以在该处设定账号密码
        /// </summary>
        /// <param name="eventArgs"></param>
        /// <returns></returns>
        public Task OnValidateConnection(ValidatingConnectionEventArgs eventArgs)
        {
            try
            {
                AppLogEntity appLog = new AppLogEntity();
                appLog.MqVersion = eventArgs.ProtocolVersion.ToString();
                appLog.Source = eventArgs.Endpoint;
                appLog.LogType = GlobalConfig.LogType.ReqConnect.ToString();
                appLog.LogTime = DateTime.Now;
                appLog.ClientId = eventArgs.ClientId;
                var user = _sqlSugar.Queryable<UserEntity>().Where(x => x.UserName == eventArgs.UserName && x.Password == eventArgs.Password.ToUpper() && x.IsDeleted == false).First();
                if (!(user?.Id > 0))
                {
                    eventArgs.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
                    appLog.Logger = $"客户端:{eventArgs.Endpoint}，ID:[{eventArgs.ClientId}]，UserName:[{eventArgs.UserName}]请求建立连接，账号密码验证不通过!";
                }
                else
                {
                    appLog.Logger = $"客户端:{eventArgs.Endpoint}，ID:[{eventArgs.ClientId}] 请求建立连接，账号密码验证通过!";
                }
                _logger.LogInformation(appLog.Logger);
                _sqlSugar.Insertable(appLog).ExecuteCommand();
                //eventArgs.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
                return Task.CompletedTask;
            }
            catch (Exception ex)
            {
                return Task.FromException(ex);
            }
        }

        /// <summary>
        /// 成功建立连接
        /// </summary>
        /// <param name="eventArgs"></param>
        /// <returns></returns>
        public Task OnClientConnected(ClientConnectedEventArgs eventArgs)
        {
            AppLogEntity appLog = new AppLogEntity();
            appLog.MqVersion = eventArgs.ProtocolVersion.ToString();
            appLog.Source = eventArgs.Endpoint;
            appLog.LogType = GlobalConfig.LogType.ReqConnectSucceed.ToString();
            appLog.LogTime = DateTime.Now;
            appLog.ClientId = eventArgs.ClientId;
            appLog.Logger = $"客户端: {eventArgs.Endpoint} ，ID:[{eventArgs.ClientId}] 成功建立连接!";
            _logger.LogInformation(appLog.Logger);
            _sqlSugar.Insertable(appLog).ExecuteCommand();
            return Task.CompletedTask;
        }



        /// <summary>
        /// 与客户端断开连接
        /// </summary>
        /// <param name="eventArgs"></param>
        /// <returns></returns>
        public Task OnClientDisconnectedAsync(ClientDisconnectedEventArgs eventArgs)
        {
            AppLogEntity appLog = new AppLogEntity();
            //var record = _sqlSugar.Queryable<AppLogEntity>().OrderBy(o => o.ClientId == eventArgs.ClientId).First();
            appLog.Source = eventArgs.Endpoint;
            appLog.LogType = GlobalConfig.LogType.ConnectBreak.ToString();
            appLog.LogTime = DateTime.Now;
            appLog.ClientId = eventArgs.ClientId;
            //appLog.MqVersion = record?.MqVersion;
            appLog.Logger = $"客户端:{eventArgs.Endpoint}，ID:[{eventArgs.ClientId}] 断开连接!";
            _logger.LogInformation(appLog.Logger);
            _sqlSugar.Insertable(appLog).ExecuteCommand();
            return Task.CompletedTask;
        }

        /// <summary>
        /// 订阅
        /// </summary>
        /// <param name="eventArgs"></param>
        /// <returns></returns>
        public Task OnClientSubscribedTopicAsync(ClientSubscribedTopicEventArgs eventArgs)
        {
            //var record = _sqlSugar.Queryable<AppLogEntity>().OrderBy(o => o.ClientId == eventArgs.ClientId && o.MqVersion!= null).First();
            AppLogEntity appLog = new AppLogEntity();
            //appLog.Source = record.Source;
            appLog.LogType = GlobalConfig.LogType.Subscribed.ToString();
            appLog.LogTime = DateTime.Now;
            appLog.ClientId = eventArgs.ClientId;
            appLog.Logger = $"客户端:{eventArgs.ClientId} 订阅主题:[{eventArgs.TopicFilter.ToString()}]!";
            //appLog.MqVersion = record.MqVersion;
            //eventArgs.
            _logger.LogInformation(appLog.Logger);
            _sqlSugar.Insertable(appLog).ExecuteCommand();

            return Task.CompletedTask;
        }
        /// <summary>
        /// 取消订阅
        /// </summary>
        /// <param name="eventArgs"></param>
        /// <returns></returns>
        public Task OnClientUnsubscribedTopicAsync(ClientUnsubscribedTopicEventArgs eventArgs)
        {
            //var record = _sqlSugar.Queryable<AppLogEntity>().OrderBy(o => o.ClientId == eventArgs.ClientId).First();
            AppLogEntity appLog = new AppLogEntity();
            //appLog.Source = record.Source;
            appLog.LogType = GlobalConfig.LogType.UnSubscribed.ToString();
            appLog.LogTime = DateTime.Now;
            appLog.ClientId = eventArgs.ClientId;
            appLog.Logger = $"客户端:{eventArgs.ClientId} 取消订阅主题:[{eventArgs.TopicFilter.ToString()}]!";
            _logger.LogInformation(appLog.Logger);
            _sqlSugar.Insertable(appLog).ExecuteCommand();
            return Task.CompletedTask;
        }

        /// <summary>
        /// 消息发布
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public Task OnInterceptingPublishAsync(InterceptingPublishEventArgs args)
        {
            try
            {
                var message = args.ApplicationMessage;
                //args.ApplicationMessage.Topic = "/main";
                var json = message.ConvertPayloadToString();
                AppLogEntity appLog = new AppLogEntity();
                appLog.LogType = GlobalConfig.LogType.Publish.ToString();
                appLog.LogTime = DateTime.Now;
                appLog.ClientId = args.ClientId; 
                appLog.Logger = $"Topic:[{message.Topic}], Message：[{json}],QualityOfServiceLevel:{message.QualityOfServiceLevel}";
                //args.ApplicationMessage.
                _logger.LogInformation(appLog.Logger);
                //现场版本加密
                try
                {
                    if (_environment.IsProduction())
                    {
                        appLog.Remark = DesEncrypt.Decrypt(json, _appConfig.DesEncryptKey);
                    }
                    else
                    {
                        appLog.Remark = json;
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "MQTT.Server 未能正常解析Payload，请检查环境配置是否正确");
                }
                _sqlSugar.Insertable(appLog).ExecuteCommand();
                return Task.CompletedTask;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "未能正常处理消息");
                return Task.FromException(ex);
            }
        }

        /// <summary>
        /// 客户端未能及时消费的数据
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public Task OnApplicationMessageNotConsumedAsync(ApplicationMessageNotConsumedEventArgs args)
        {
            Console.WriteLine("OnApplicationMessageNotConsumedAsync:" + args.ApplicationMessage.Topic);
            Console.WriteLine("OnApplicationMessageNotConsumedAsync:" + args.ApplicationMessage.ConvertPayloadToString());
            return Task.CompletedTask;
        }

        public Task OnClientAcknowledgedPublishPacketAsync(ClientAcknowledgedPublishPacketEventArgs e)
        {
            Console.WriteLine($"Client '{e.ClientId}' acknowledged packet {e.PublishPacket.PacketIdentifier} with topic '{e.PublishPacket.Topic}'");

            // It is also possible to read additional data from the client response. This requires casting the response packet.
            var qos1AcknowledgePacket = e.AcknowledgePacket as MqttPubAckPacket;
            Console.WriteLine($"QoS 1 reason code: {qos1AcknowledgePacket?.ReasonCode}");

            var qos2AcknowledgePacket = e.AcknowledgePacket as MqttPubCompPacket;
            Console.WriteLine($"QoS 2 reason code: {qos1AcknowledgePacket?.ReasonCode}");

            return Task.CompletedTask;
        }


        public Task OnStoppedAsync(EventArgs args)
        {
            AppLogEntity appLog = new AppLogEntity();
            //appLog.MqVersion = eventArgs.ProtocolVersion.ToString();
            //appLog.Source = eventArgs.Endpoint;
            appLog.LogType = GlobalConfig.LogType.StopService.ToString();
            appLog.LogTime = DateTime.Now;
            //appLog.ClientId = args.;
            appLog.Logger = $"服务端程序退出!";
            _logger.LogInformation(appLog.Logger);
            _sqlSugar.Insertable(appLog).ExecuteCommand();
            return Task.CompletedTask;
        }

        #endregion

    }
}
